package com.xzs.kit.base.jwt;

import com.xzs.kit.base.constant.Constant;
import com.xzs.kit.base.util.DateUtil;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jws;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;

import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
import javax.xml.bind.DatatypeConverter;
import java.security.Key;
import java.util.Calendar;
import java.util.Date;
import java.util.Map;


/**
 * jwt生成token工具
 * @author: Victor.Xiao
 * @create: 2018-08-09 08:49
 */
public class JWTUtil {

    /**
     * @Description  生成token
     * @author Victor.Xiao
     * @date 2018-08-09 10:50
     * @param userId 用户信息
     * @param userName 用户名
     * @param subject 所有者
     * @param privateKey 秘钥
     * @param expire 时效时间 秒
     * @return java.lang.String 令牌
     * @throws
    */
    public static String generateToken(String userId,String userName,String subject, String privateKey, int expire) {
        Date expireDate = DateUtil.add(new Date(), Calendar.SECOND,expire);
        Key key = generalKey(privateKey);
        String compactJws = Jwts.builder()
                .setSubject(subject)
                .claim(Constant.JWT_KEY_USER_ID, userId)
                .claim(Constant.JWT_KEY_USERNAME, userName)
                .setExpiration(expireDate)
                .setIssuedAt(new Date())
                .signWith(SignatureAlgorithm.HS256, key)
                .compact();
        return compactJws;
    }

    /**
     * @Description  生成token
     * @author Victor.Xiao
     * @date 2018-08-09 10:50
     * @param userId 用户信息
     * @param userName 用户名
     * @param privateKey 秘钥
     * @return java.lang.String 令牌
     * @throws
     */
    public static String generateToken(String userId,String userName, String privateKey ) {
        return generateToken(userId,userName,"default",privateKey, Constant.JWT_DEFAULT_EXPIRE);
    }

    /**
     * @description : 密钥加密token
     * @author : Victor.Xiao
     * @param jwtInfo 需要的用户信息
     * @param privateKey 加密秘钥
     * @param expire 失效时间,单位秒
     * @return
     * @throws Exception
     */
    public static String generateToken(JWTInfo jwtInfo, String privateKey, int expire) {
        Date expireDate = DateUtil.add(new Date(), Calendar.SECOND,expire);
        Key key = generalKey(privateKey);
        String compactJws = Jwts.builder()
                .setSubject(jwtInfo.getSubject())
                .claim(Constant.JWT_KEY_USER_ID, jwtInfo.getUserId())
                .claim(Constant.JWT_KEY_USERNAME, jwtInfo.getUserName())
                .setExpiration(expireDate)
                .setIssuedAt(new Date())
                .signWith(SignatureAlgorithm.HS256, key)
                .compact();
        return compactJws;
    }

    /**
     * 长度太小的key不能通过,默认加长度好像至少要5
     * @param privateKey
     * @return
     */
    public static String getPrivateKey(String privateKey){
        if(privateKey==null||privateKey.length()<4){
            privateKey+="aaaaaaa";
        }
        return privateKey;
    }


    /**
     * @description : 密钥加密token
     * @author : Victor.Xiao
     * @param jwtInfo 需要的用户信息
     * @param privateKey 加密秘钥
     * @return
     * @throws Exception
     */
    public static String generateToken(JWTInfo jwtInfo, String privateKey ) {
        return generateToken(jwtInfo,privateKey, Constant.JWT_DEFAULT_EXPIRE);
    }

    /**
     * @description : 解析token
     * @author : Victor.Xiao
     * @param token
     * @param privateKey
     * @return
     * @throws Exception
     */
    public static Jws<Claims> parserToken(String token, String privateKey)  {
        privateKey = getPrivateKey(privateKey);
        Jws<Claims> claimsJws = Jwts.parser().setSigningKey(privateKey).parseClaimsJws(token);
        return claimsJws;
    }

    /**
     * @description : 获取token中的用户信息
     * @author : Victor.Xiao
     * @param token 令牌
     * @param privateKey  秘钥
     * @return
     * @throws Exception
     */
    public static JWTInfo getInfoFromToken(String token, String privateKey) {
        Jws<Claims> claimsJws = parserToken(token, privateKey);
        Claims body = claimsJws.getBody();
        JWTInfo jwt = new JWTInfo();
        jwt.setSubject(body.getSubject());
        jwt.setExpiration(body.getExpiration());
        jwt.setIssuedAt(body.getIssuedAt());
        jwt.setUserId(body.get(Constant.JWT_KEY_USER_ID).toString());
        jwt.setUserName(body.get(Constant.JWT_KEY_USERNAME).toString());
        return jwt;
    }


    /**
     * @description : 获取token中的用户信息
     * @author : Victor.Xiao
     * @param token 令牌
     * @param privateKey  秘钥
     * @return
     * @throws Exception
     */
    public static Map<String,Object> getParamsFromToken(String token, String privateKey) {
        Jws<Claims> claimsJws = parserToken(token, privateKey);
        Claims body = claimsJws.getBody();
        return body;
    }

    /**
     * @description : base64加密的秘钥
     * @author : Victor.Xiao
     * @param privateKey 秘钥
     * @return
     */
    public static SecretKey generalKey(String privateKey){
        privateKey = getPrivateKey(privateKey);
        return  new SecretKeySpec(DatatypeConverter.parseBase64Binary(privateKey),SignatureAlgorithm.HS256.getJcaName());
    }


}
